/*
 * This work is licensed under a GNU General Public License 
 * (http://www.gnu.org/copyleft/gpl.html).
 *
 * Title: 		Mobup
 * Description:         Mobile uploader for Flickr
 * Version: 		0.3
 * Creator:             Vincenzo Lembo and Matteo Penzo
 * Source:              http://mobup.org
 *
 */


package ctmobup.flickr;

import ctmobup.utils.*;
import javax.microedition.lcdui.*;

import uns.fit.gis.mapdrawer.MapCanvas;
import ctmobup.utils.*;
import java.util.*;


/*
 * Flickr Class
 *
 * Object to activate flickr account for uploading the images
 * and for attaching the image properties.
 *
 */

public class Flickr {

    private String api_key;
    private String auth_token;
    private String secret_shared;
    private String api_sig;
    private String method;
    private String signature;
    private String autentication_url;
    private String mini_token;
    private String querystring;
    public String[][] Blogs;
    public String[] Tags;
    public String[][] Sets;
    public String[][] GroupsPools;
    private	int lastCode=-1;
    private String lastErrorMsg;

    /** Creates a new instance of Flickr */
    public Flickr(String key,String secret) {

        //get the Api_key, Secret Shared and Auth_Token from RecordStore of device
        api_key = key;
        secret_shared = secret;
        auth_token = Configuration.Get("token");
    }

    /**
     * Return last error message 
     * 
     */
    public String getLastErrorMsg(){
    	return lastErrorMsg;
    }

    /**
     * Return last error code
     */
    public int getLastErrorCode(){
    	return lastCode;
    }
    private void fillErrorMsgAndCode(String inResp)
    {
    	try{
    		lastCode=Integer.parseInt(GetField(inResp,"err","code"));
    	}catch(Exception e){
    		lastCode=-1;
    	}
    	lastErrorMsg=GetField(inResp,"err","msg");
    }
	/*
     * Set the application for upload the image on flickr account
     * Get and store the autentication token
     *
     * Parameter:
     * api_key   (retrieved on flickr accout option)
     * secret shared (retrieved on flickr accout option)
     * minitoken (retrieved on flickr accout option)
     *
     */
    public boolean Registration(String minitoken)
    {
        //set the mini_Token inserted from user
        mini_token = minitoken;

        try
        {
            //string for signature: secret_shared + api_key + method_name + minitoken
            signature = secret_shared + "api_key" + api_key + "methodflickr.auth.getFullTokenmini_token" + mini_token;
            //MD5 signature for request
            api_sig = MD5.getHashString(signature);

            String resp_full_token = "";
            resp_full_token = HTTP.sendGetRequest("http://www.flickr.com/services/rest/?method=flickr.auth.getFullToken&api_key=" + api_key + "&mini_token=" + mini_token + "&api_sig=" + api_sig);
            //get full_token from response
            auth_token = GetParameter(resp_full_token, "token");

            //store Auth_Token in RecordStore of device
            Configuration.Set("token", auth_token);
            //check for autentication error
            if(auth_token!="")
                return true;
            else{
            	fillErrorMsgAndCode(resp_full_token);
                return false;
            }
        }
        catch(Exception e)
        {
            return false;
        }
    }

    /*
     * Build the post request for upload image on Flickr.
     *
     * Parameters:
     * data (byte[]) of photo
     * title of photo
     * description of photo
     * tags of photo (separated by space)
     */
    public String SendPhoto(byte[] photoData,String photoTitle,String photoDesc,String _tags)
    {
        //properties for image to upload
        String title = photoTitle;
        String description = photoDesc;
        String tags = "mobilemap05 cameraphone " + _tags; //adding tag "mobup" to any image uploaded
        String is_public = "1"; //image is public
        String is_friend = "1"; //image is friend
        String is_family = "1"; //image is family

        //string signature for sign request to flickr service
        signature = secret_shared + "api_key" + api_key + "auth_token" + auth_token;

        //add properties of the image
        if(description!="")
            signature += "description" + description;
        if(is_family!="")
            signature += "is_family" + is_family;
        if(is_friend!="")
            signature += "is_friend" + is_friend;
        if(is_public!="")
            signature += "is_public" + is_public;
        if(tags!="")
            signature += "tags" + tags;
        if(title!="")
            signature += "title" + title;

        //MD5 signature for request
        api_sig = MD5.getHashString(signature);

        //build post request
        String boundary = GenerateBoundary();
        String before =
            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_key\"\r\n" +
            "\r\n" +
            api_key + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"auth_token\"\r\n" +
            "\r\n" +
            auth_token + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_sig\"\r\n" +
            "\r\n" +
            api_sig + "\r\n";

        if(title!="")
        {
            before += "--" + boundary + "\r\n" +
                "Content-Disposition: form-data; name=\"title\"\r\n" +
                "\r\n" +
                title + "\r\n";
        }

        if(description!="")
        {
            before += "--" + boundary + "\r\n" +
                "Content-Disposition: form-data; name=\"description\"\r\n" +
                "\r\n" +
                description + "\r\n";
        }

        if(tags!="")
        {
            before += "--" + boundary + "\r\n" +
                "Content-Disposition: form-data; name=\"tags\"\r\n" +
                "\r\n" +
                tags + "\r\n";
        }

        if(is_public!="")
        {
            before += "--" + boundary + "\r\n" +
                "Content-Disposition: form-data; name=\"is_public\"\r\n" +
                "\r\n" +
                is_public + "\r\n";
        }

        if(is_friend!="")
        {
            before += "--" + boundary + "\r\n" +
                "Content-Disposition: form-data; name=\"is_friend\"\r\n" +
                "\r\n" +
                is_friend + "\r\n";
        }

        if(is_family!="")
        {
            before += "--" + boundary + "\r\n" +
                "Content-Disposition: form-data; name=\"is_family\"\r\n" +
                "\r\n" +
                is_family + "\r\n";
        }

        before += "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"photo\"; filename=\"test.jpg\"\r\n" +
            "Content-Type: image/jpeg\r\n" +
            "\r\n";
        
        /*
        Image image = Image.createImage(photoData, 0,photoData.length);
        String imageString = new String(photoData);
        post += imageString;
		*/

        String after = "\r\n" +
                "--" + boundary + "--\r\n";

        //send post request
        String Response = HTTP.sendPostRequest(before, photoData, after, "http://www.flickr.com/services/upload/", boundary);
        //get photoid from response
        String idPhoto = GetParameter(Response, "photoid");
        System.out.println(Response);
        if(idPhoto.equals("")){
        	fillErrorMsgAndCode(Response);
        }
        else {
        	System.out.println(Response);
        	if(MapCanvas.earthPosition != null)
        		setPhotoLocation(idPhoto);
        }
        return idPhoto;
    }
    
    public boolean setPhotoLocation(String photoId) {
    	signature = secret_shared + "api_key" + api_key
        			+ "auth_token" + auth_token
        			+ "lat" + MapCanvas.earthPosition.getLatitude().toString()
        			+ "lon" + MapCanvas.earthPosition.getLongitude().toString()
        			+ "methodflickr.photos.geo.setLocation"
        			+ "photo_id" + photoId;
    	api_sig = MD5.getHashString(signature);
        String boundary = GenerateBoundary();
        String post =
            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_key\"\r\n" +
            "\r\n" +
            api_key + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"auth_token\"\r\n" +
            "\r\n" +
            auth_token + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"photo_id\"\r\n" +
            "\r\n" +
            photoId + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"lat\"\r\n" +
            "\r\n" +
            MapCanvas.earthPosition.getLatitude().toString() + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"lon\"\r\n" +
            "\r\n" +
            MapCanvas.earthPosition.getLongitude().toString() + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_sig\"\r\n" +
            "\r\n" +
            api_sig + "\r\n"

            + "--" + boundary + "--\r\n";

        //send post request
        String resp = HTTP.sendPostRequest(post, "http://www.flickr.com/services/rest/?method=flickr.photos.geo.setLocation", boundary);

        if(resp.indexOf("stat=\"ok\"")>-1) {
        	System.out.println(resp);
            return true;
        }
        else{
        	fillErrorMsgAndCode(resp);
        	System.out.println(resp);
            return false;
        }
    }
    
    /*
     * Blog the photo on flickr account.
     *
     * Parameters:
     * id of photo
     * id of blog
     * title of post
     * description of post
     */
    public boolean BlogPhoto(String photoid,String blogid,String title,String desc)
    {
        //string signature for sign request to flickr service
        signature = secret_shared + "api_key" + api_key
                + "auth_token" + auth_token
                + "blog_id" + blogid
                + "description" + desc
                + "methodflickr.blogs.postPhoto"
                + "photo_id" + photoid
                + "title" + title;
        api_sig = MD5.getHashString(signature);

        String boundary = GenerateBoundary();
        String post =
            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_key\"\r\n" +
            "\r\n" +
            api_key + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"auth_token\"\r\n" +
            "\r\n" +
            auth_token + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"blog_id\"\r\n" +
            "\r\n" +
            blogid + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"description\"\r\n" +
            "\r\n" +
            desc + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"photo_id\"\r\n" +
            "\r\n" +
            photoid + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"title\"\r\n" +
            "\r\n" +
            title + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_sig\"\r\n" +
            "\r\n" +
            api_sig + "\r\n"

            + "--" + boundary + "--\r\n";

        //send post request
        String resp = HTTP.sendPostRequest(post, "http://www.flickr.com/services/rest/?method=flickr.blogs.postPhoto", boundary);

        if(resp.indexOf("stat=\"ok\"")>-1)
            return true;
        else{
        	fillErrorMsgAndCode(resp);
            return false;
        }
    }


    /*
     * Add the photo on sets flickr account.
     *
     * Parameters:
     * id of photo
     * id of set
     *
     */
    public boolean AddToPhotoSet(String photoid,String setid)
    {
        //string signature for sign request to flickr service
        signature = secret_shared + "api_key" + api_key
                + "auth_token" + auth_token
                + "methodflickr.photosets.addPhoto"
                + "photo_id" + photoid
                + "photoset_id" + setid;
        api_sig = MD5.getHashString(signature);

        String boundary = GenerateBoundary();
        String post =
            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_key\"\r\n" +
            "\r\n" +
            api_key + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"auth_token\"\r\n" +
            "\r\n" +
            auth_token + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"photo_id\"\r\n" +
            "\r\n" +
            photoid + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"photoset_id\"\r\n" +
            "\r\n" +
            setid + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_sig\"\r\n" +
            "\r\n" +
            api_sig + "\r\n"

            + "--" + boundary + "--\r\n";

        //send post request
        String resp = HTTP.sendPostRequest(post, "http://www.flickr.com/services/rest/?method=flickr.photosets.addPhoto", boundary);

        if(resp.indexOf("stat=\"ok\"")>-1)
            return true;
        else{
        	fillErrorMsgAndCode(resp);
            return false;
        }
    }


    
    public boolean AddToGroup(String photoid,String groupid)
    {
        //string signature for sign request to flickr service
        signature = secret_shared + "api_key" + api_key
                + "auth_token" + auth_token
                + "group_id" + groupid
                + "methodflickr.groups.pools.add"
                + "photo_id" + photoid;
        api_sig = MD5.getHashString(signature);

        String boundary = GenerateBoundary();
        String post =
            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_key\"\r\n" +
            "\r\n" +
            api_key + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"auth_token\"\r\n" +
            "\r\n" +
            auth_token + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"photo_id\"\r\n" +
            "\r\n" +
            photoid + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"group_id\"\r\n" +
            "\r\n" +
            groupid + "\r\n" +

            "--" + boundary + "\r\n" +
            "Content-Disposition: form-data; name=\"api_sig\"\r\n" +
            "\r\n" +
            api_sig + "\r\n"

            + "--" + boundary + "--\r\n";

        //send post request
        String resp = HTTP.sendPostRequest(post, "http://www.flickr.com/services/rest/?method=flickr.groups.pools.add", boundary);

        if(resp.indexOf("stat=\"ok\"")>-1)
            return true;
        else{
        	fillErrorMsgAndCode(resp);
            return false;
        }
    }

    /*
     * Get the list of blogs for flickr user's account
     * This method fill in the array property Blogs with the names and ids of blogs
     */
    public void GetBlogList()
    {
        //string signature for sign request to flickr service
        signature = secret_shared + "api_key" + api_key + "auth_token" + auth_token + "methodflickr.blogs.getList";
        api_sig = MD5.getHashString(signature);

        String resp = HTTP.sendGetRequest("http://www.flickr.com/services/rest/?method=flickr.blogs.getList&api_key=" + api_key + "&auth_token=" + auth_token + "&api_sig=" + api_sig);
        String tmpResp = resp.toString();

        // Format of response for blog list request:
        //<blogs>
        //        <blog id="73" name="Bloxus test" needspassword="0"
        //                url="http://remote.bloxus.com/" />
        //        <blog id="74" name="Manila Test" needspassword="1"
        //                url="http://flickrtest1.userland.com/" />
        //</blogs>

        //count the blog
        int numBlog = 0;
        while(tmpResp.indexOf("<blog id")>-1)
        {
            tmpResp = tmpResp.substring(tmpResp.indexOf("<blog id") + 8);
            numBlog++;
        }

        //initialize the dimension of array
        String[][] BlogsArray = new String[2][numBlog];

        //fill array
        int i = 0;
        while(resp.indexOf("<blog id")>-1)
        {
            int posTag = resp.indexOf("<blog id");
            int posId = resp.indexOf("id=\"", posTag);
            int posName = resp.indexOf("name=\"", posId);
            String id = resp.substring(posId + 4, resp.indexOf("\"", posId + 4));
            String name = resp.substring(posName + 6, resp.indexOf("\"", posName + 6));
            BlogsArray[0][i] = id;
            BlogsArray[1][i] = name;
            resp = resp.substring(posName + 8);
            i++;
        }
        this.Blogs = BlogsArray;
    }

    public void GetSetsList()
    {
        //string signature for sign request to flickr service
        signature = secret_shared + "api_key" + api_key + "auth_token" + auth_token + "methodflickr.photosets.getList";
        api_sig = MD5.getHashString(signature);

        String resp = HTTP.sendGetRequest("http://www.flickr.com/services/rest/?method=flickr.photosets.getList&api_key=" + api_key + "&auth_token=" + auth_token + "&api_sig=" + api_sig);
        String tmpResp = resp.toString();

        // Format of response for sets list request:
        //<photosets cancreate="1">
        //    <photoset id="5" primary="2483" secret="abcdef"
        //            server="8" photos="4">
        //            <title>Test</title>
        //            <description>foo</description>
        //    </photoset>
        //    <photoset id="4" primary="1234" secret="832659"
        //            server="3" photos="12">
        //            <title>My Set</title>
        //            <description>bar</description>
        //    </photoset>
        //</photosets>


        //count the blog
        int numSets = 0;
        while(tmpResp.indexOf("<photoset id")>-1)
        {
            tmpResp = tmpResp.substring(tmpResp.indexOf("<photoset id") + 12);
            numSets++;
        }

        //initialize the dimension of array
        String[][] SetsArray = new String[2][numSets];

        //fill array
        int i = 0;
        while(resp.indexOf("<photoset id")>-1)
        {
            int posTag = resp.indexOf("<photoset id");
            int posId = resp.indexOf("id=\"", posTag);
            int posName = resp.indexOf("<title>", posId);
            String id = resp.substring(posId + 4, resp.indexOf("\"", posId + 4));
            String name = resp.substring(posName + 7, resp.indexOf("</title>", posName + 7));
            SetsArray[0][i] = id;
            SetsArray[1][i] = name;
            resp = resp.substring(posName + 12);
            i++;
        }
        this.Sets = SetsArray;
    }

     public void GetTagsList()
    {
        //string signature for sign request to flickr service
        signature = secret_shared + "api_key" + api_key + "auth_token" + auth_token + "count10methodflickr.tags.getListUserPopular";
        api_sig = MD5.getHashString(signature);

        String resp = HTTP.sendGetRequest("http://www.flickr.com/services/rest/?method=flickr.tags.getListUserPopular&api_key=" + api_key + "&auth_token=" + auth_token + "&api_sig=" + api_sig + "&count=10");
        String tmpResp = resp.toString();

        // Format of response for popular tags list request:
        //<who id="12037949754@N01">
        //    <tags>
        //            <tag count="10">bar</tag>
        //            <tag count="11">foo</tag>
        //            <tag count="147">gull</tag>
        //            <tag count="3">tags</tag>
        //            <tag count="3">test</tag>
        //    </tags>
        //</who>


        //count the tags
        int numTags = 0;
        while(tmpResp.indexOf("<tag count")>-1)
        {
            tmpResp = tmpResp.substring(tmpResp.indexOf("<tag count") + 10);
            numTags++;
        }
        if(resp.indexOf(">mobup<")>-1)
            numTags--;
        
        if(resp.indexOf(">cameraphone<")>-1)
            numTags--;

        //initialize the dimension of array
        String[] TagsArray = new String[numTags];

        //fill array
        int i = 0;
        while(resp.indexOf("<tag count")>-1)
        {
            int posTag = resp.indexOf("<tag count");
            String tag = resp.substring(resp.indexOf(">",posTag + 10) + 1,resp.indexOf("<",posTag + 10));
            resp = resp.substring(posTag + 10);
            if(!tag.equals(new String("mobup")) && !tag.equals(new String("cameraphone")))
            {
                TagsArray[i] = tag;
                i++;
            }
        }
        this.Tags = TagsArray;
    }

     
    public void GetGroupsPoolsList()
    {
        //string signature for sign request to flickr service
        signature = secret_shared + "api_key" + api_key + "auth_token" + auth_token + "methodflickr.groups.pools.getGroups";
        api_sig = MD5.getHashString(signature);

        String resp = HTTP.sendGetRequest("http://www.flickr.com/services/rest/?method=flickr.groups.pools.getGroups&api_key=" + api_key + "&auth_token=" + auth_token + "&api_sig=" + api_sig);
        String tmpResp = resp.toString();

        // Format of response for sets list request:
        //<groups>
        //        <group nsid="33853651696@N01" name="Art and Literature Hoedown"
        //                admin="0" privacy="3" photos="2" />
        //        <group nsid="34427465446@N01" name="FlickrIdeas"
        //                admin="1" privacy="3" photos="20" />
        //        <group nsid="34427465497@N01" name="GNEverybody"
        //                admin="0" privacy="3" photos="4" />
        //</groups>



        //count the blog
        int numGroups = 0;
        while(tmpResp.indexOf("<group ")>-1)
        {
            tmpResp = tmpResp.substring(tmpResp.indexOf("<group ") + 7);
            numGroups++;
        }

        //initialize the dimension of array
        String[][] GroupsArray = new String[2][numGroups];

        //fill array
        int i = 0;
        while(resp.indexOf("<group ")>-1)
        {
            int posGroup = resp.indexOf("<group ");
            int posId = resp.indexOf("nsid=\"", posGroup);
            int posName = resp.indexOf("name=\"", posId);
            String id = resp.substring(posId + 6, resp.indexOf("\"", posId + 6));
            String name = resp.substring(posName + 6, resp.indexOf("\"", posName + 7));
            GroupsArray[0][i] = id;
            GroupsArray[1][i] = name;
            resp = resp.substring(posName + 1);
            i++;
        }
        this.GroupsPools = GroupsArray;
    }


    /*
     * Get the value of the tag in the xml response
     */
    private String GetParameter(String str,String param)
    {
        String startTag = "<" + param + ">";
        String endTag = "</" + param + ">";
        if(str.indexOf(startTag)>-1 && str.indexOf(endTag)>-1)
        {
            if(str.indexOf(startTag) + startTag.length() < str.indexOf(endTag))
            {
                return str.substring(str.indexOf(startTag) + startTag.length(), str.indexOf(endTag));
            }
            else
            {
                return "";
            }
        }
        else
        {
            return "";
        }
    }
    /*
     * Get the value of the tag in the xml response
     */
    private String GetField(String str,String param,String field)
    {
        String startTag = "<" + param;
        String endTag = "/>";
        if(str.indexOf(startTag)>-1 && str.indexOf(endTag)>-1)
        {
            if(str.indexOf(startTag) + startTag.length() < str.indexOf(endTag))
            {
                String theString=str.substring(str.indexOf(startTag) + startTag.length(), str.indexOf(endTag));
                System.out.println(theString);
                startTag=field+"=\"";
                endTag="\"";
                int start=theString.indexOf(startTag);
                if(start>-1 && theString.indexOf(endTag,start)>-1)
                {
                    if(theString.indexOf(startTag) + startTag.length() < theString.indexOf(endTag,start+startTag.length()))
                    {
                    	System.out.println(theString.indexOf(startTag) + startTag.length()+ "\n"+ theString.indexOf(endTag,start+startTag.length()));
                        return theString.substring(theString.indexOf(startTag) + startTag.length(), theString.indexOf(endTag,start+startTag.length()));
                   
                    }
                }
            }
        }
        return "";
    }

    /*
     * Generate the boundary for post request with Content-Type multipart/form-data
     */
    private String GenerateBoundary()
    {
        String boundary ="";
        Random random = new Random();
        Date date = new Date();
        random.setSeed(date.getTime());

        boundary += Integer.toHexString(random.nextInt());
        boundary += Integer.toHexString(random.nextInt());

        return "---------------------------" + boundary.substring(4);
    }
}
